<template>
  <div>
    <cv-toast-transition
      class="cv-toast-transition cv-toast-top cv-toast-right"
      style="flex-direction: column"
      transition="cv-toast-right"
      :position="settings.position"
      >

      <cv-toast-container
        v-for="status in toasts"
        v-bind:key="status.id"
        class="vt-notification"
        :status="status"
        :base-icon-class="settings.baseIconClass"
      />

    </cv-toast-transition>
  </div>
</template>

<script>
import Toast from './cv-toast-container';
import Transition from './cv-toast-transition';

const isBoolean = value => typeof value === "boolean";
// const isString = value => typeof value === "string";
// const isObject = value => typeof value === "object";
const between = (min, max, value) => value > min && value <= max;

export default {
  name: 'CvToastController',
  components: {
    'cv-toast-container': Toast,
    'cv-toast-transition': Transition,
  },  
  data: function() {
    return {
      toasts: [],
      queue: [],
      settings: {
        position: 'top-right',
        // position: 'bottom-right',
        canTimeout: true,
        successDuration: 4000,
      },
      visible: true,
      "title": "notification title",
      "subTitle": "a subtitle",
      "caption": "Time stamp [00:00:00]",
      lowContrast: true      
    }
  }, 
  mounted() {
    console.log('toast controller mounted!!');
    // this.setSettings();
    // listen for notification event
    this.$root.$on(
      ["vtFinished", "vtDismissed", "vtPromptResponse", "vtLoadStop"],
      payload => {
        if (typeof payload.id === "string") {
          this.remove(payload.id);
        }
      }
    );
    if (
      window.notification &&
      window.notification.type &&
      window.notification.body
    ) {
      const delay = window.notification.delay ? window.notification.delay : 0;
      setTimeout(() => {
        this.add(window.notification);
      }, delay);
    }
  },  
  methods: {
    error(toastText) {
      console.log(('adding new toast in controller! - ' + toastText));
        const status = {
          body: "ok",
          title: toastText,
        };
        status.type = "error";
        this.add(status);
    },    
    success(toastText) {
      console.log(('adding new toast in controller! - ' + toastText));
        const status = {
          body: "ok",
          title: toastText,
        };
        status.type = 'success';
        this.add(status);
    },
    findToast(id) {
      return this.toasts.findIndex(toast => {
        return toast.id === id;
      });
    },    
    findQueuedToast(id) {
      return this.queue.findIndex(toast => {
        return toast.id === id;
      });
    },    
    // UUID function can eventually be relaced by this when approved:
    // https://github.com/tc39/proposal-uuid
    uuidv4() {
      return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
        (
          c ^
          (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))
        ).toString(16)
      );
    },
    getTitle(status) {
      if (status.title) {
        return status.title;
      }
      return "Info";
    },
    add(status) {
      // copy object
      let toast = Object.assign({}, status); //todo update to deep copy
      // if object doesn't have default values, set them
      //todo update these to object merger
      toast.duration = this.settings.warningInfoDuration;
      if (Number(status.duration) > 0) {
        toast.duration = Number(status.duration);
      } else if (status.type) {
        toast.duration =
          status.type === "error"
            ? this.settings.errorDuration
            : status.type === "success"
            ? this.settings.successDuration
            : this.settings.warningInfoDuration;
      }
      toast.answers =
        status.answers && Object.keys(status.answers).length > 0
          ? status.answers
          : { Yes: true, No: false };
      toast.canPause = isBoolean(status.canPause)
        ? status.canPause
        : this.settings.canPause;
      toast.hideProgressbar = isBoolean(status.hideProgressbar)
        ? status.hideProgressbar
        : this.settings.hideProgressbar;
      toast.id = this.uuidv4();
      toast.title = this.getTitle(status);
      toast.canTimeout = isBoolean(status.canTimeout)
        ? status.canTimeout
        : this.settings.canTimeout;
      toast.iconEnabled = isBoolean(status.iconEnabled)
        ? status.iconEnabled
        : this.settings.iconEnabled;
      if (["prompt", "loader"].indexOf(status.mode) === -1) {
        toast.draggable = isBoolean(status.draggable)
          ? status.draggable
          : this.settings.draggable;
      } else {
        toast.draggable = false;
      }
      toast.dragThreshold = between(0, 5, status.dragThreshold)
        ? status.dragThreshold
        : this.settings.dragThreshold;
      if (status.mode === "prompt" || status.mode === "loader") {
        toast.canTimeout = false;
      }

      toast.theme = status.theme ? status.theme : this.settings.theme;
      if (this.settings.singular && this.toasts.length > 0) {
        this.$set(this.queue, this.queue.length, toast);
        return toast.id;
      }
      this.$set(this.toasts, this.toasts.length, toast);
      return toast.id;
    },
    remove(id = null) {
      if (id) {
        let index = this.findQueuedToast(id);
        if (this.settings.singular && index !== -1) {
          this.$delete(this.queue, index);
          return this.currentlyShowing;
        }
        index = this.findToast(id);
        if (index !== -1) {
          this.$delete(this.toasts, index);
          return this.currentlyShowing;
        }
        return false;
      }
      this.toasts = [];
      return this.currentlyShowing;
    },        
    doClose(ev) {
      this.visible = false;
      console.log('ACTION close');
      console.log(ev);
    },
  }, 
  beforeDestroy() {
    this.$root.$off([
      "vtFinished",
      "vtDismissed",
      "vtPromptResponse",
      "vtLoadStop"
    ]);
  }
};
</script>

<style lang="scss">
@import '@carbon/motion/scss/motion.scss';

.cv-toast-transition {
  box-sizing: border-box;
  display: flex;
  position: fixed;
  /* width: 100%; */
  margin: 10px;
  flex-direction: column;
  z-index: 9999;
  right: 0;
  bottom: 0;
  width: auto;
  height: auto;
}

.cv-toast-default-position {
  transform: translateX(0);
  transition: all 100ms ease;
}

.cv-toast-move {
  // Supplies the standard easing curve, using the productive mode by default 
  transition-timing-function: carbon--motion(standard);  
  // transition-timing-function: ease-in-out;
  transition-property: all;
  transition-duration: 200ms !important; 
}

// .vt-bottom {
//   bottom: 0;
// }

// .cv-toast-right {
//   right: 0;
// }

.cv-toast-top {
  top: 40px;
}

.cv-toast-bottom {
  bottom: 0;
}

.cv-toast-right {
  right: 0;
}

.cv-toast-right-enter-active,
.cv-toast-left-enter-active,
.cv-toast-bottom-enter-active,
.cv-toast-top-enter-active,
.cv-toast-center-enter-active {
  transition: all 0.2s ease-out;
}

.cv-toast-right-leave-active,
.cv-toast-left-leave-active,
.cv-toast-bottom-leave-active,
.cv-toast-top-leave-active,
.cv-toast-center-leave-active {
  transition: all 0.2s ease-in;
}

.cv-toast-right-enter,
.cv-toast-right-leave-to {
  transform: translateX(50px);
  opacity: 0;
}

// .vt-left-enter,
// .vt-left-leave-to {
//   transform: translateX(-50px);
//   opacity: 0;
// }

.cv-toast-bottom-enter,
.cv-toast-bottom-leave-to {
  transform: translateY(50px);
  opacity: 0;
}

.cv-toast-top-enter,
.cv-toast-top-leave-to {
  transform: translateY(-50px);
  opacity: 0;
}

// .vt-center-enter,
// .vt-center-leave-to {
//   opacity: 0;
// }

.bx--content {
  // JPK: needed in order to get fixed positioning of toast notification to work
  transform: none; 
}

</style>